// ------------------------------------------------------------------------------------------------------------------------
// ==UserScript==
// @name           SWFStorage system
// @description    Provides Access to Flash Coookie
// @version        1.2
// @license        Creative Commons 2.0 BY-NC-SA (http://creativecommons.org/licenses/by-nc-sa/2.0/pl)
// @author         Nexces
// @include        http://pl*.plemiona.pl/game.php*
// ==/UserScript==
// ------------------------------------------------------------------------------------------------------------------------


/**
 *	You can put this script in your file directly (everything between "START COPY HERE" and "END COPY HERE") but be absolutley sure that the object is initiated before it is needed
 */

/*		START COPY HERE */
function DS_userScript_SWFStore_Wrapper() {

JSON = {
	$specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},

	$replaceChars: function(chr){
		return this.JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
	},

	encode: function(obj){
		switch (typeof obj){
			case 'string':
				return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
			case 'array':
				return '[' + String(obj.map(JSON.encode).clean()) + ']';
			case 'object': case 'hash':
				var string = [];
				for (var prop in obj) {
					if (obj.hasOwnProperty(prop)) {
						var json = JSON.encode(obj[prop]);
						if (json) {
							string.push(JSON.encode(prop) + ':' + json);
						}
					}
				}
				return '{' + string + '}';
			case 'number': case 'boolean': return String(obj);
			case false: return 'null';
		}
		return null;
	},

	decode: function(string, secure){
		if ((typeof string != 'string') || !string.length) return null;
		if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
		return eval('(' + string + ')');
	}
};

DS_userScript_SWFStore = {
	options : {
		SWFAddress : 'flashStorage.swf',
		storageName : 'myStorage',
		runAfter : function(){},
		logger : function(){}
	},
	doSaves : true,
	initialize : function (options) {

		options = options || {};
		this.options.SWFAddress = options.SWFAddress || this.options.SWFAddress;
		this.options.storageName = options.storageName || this.options.storageName;
		this.options.runAfter = options.runAfter || this.options.runAfter;
		this.options.logger = options.logger || this.options.logger;

		this.storageSuffix = "_" + this._time() + "_" + Math.round(Math.random() * 100000);
		// We DO NEED an unique instance of the flash object as it will "work" on a different cookie
		this.createUniqueInstance();
		return this;
	},
	createUniqueInstance : function () {
		var browserId, value, date, div, object;
		value = document.cookie.match('(?:^|;)\\s*' + 'DS_userScript_SWFStore' + '=([^;]*)');
		browserId = (value) ? decodeURIComponent(value[1]) : null;
		if (!browserId) {
			browserId = Math.round(Math.random() * Math.PI * 100000);
			value = encodeURIComponent(browserId);
			date = new Date();
			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
			value += '; expires=' + date.toGMTString();
			document.cookie = 'DS_userScript_SWFStore' + '=' + value;
		}

		div = document.createElement('div');
		div.id = 'DS_userScript_SWFStoreContainer'+this.storageSuffix;
		div.style.position = 'absolute';
		div.style.width = '300px';
		div.style.height = '200px';
		div.style.display = 'block';
		div.style.top = '100px';
		div.style.left = '-299px';
		div.style.overflow = 'hidden';
		document.getElementById('ds_body').appendChild(div);

		this.options.logger('SWFStore.createUniqueInstance() :: SWFAddress: '+this.options.SWFAddress,8);
		this.options.logger('SWFStore.createUniqueInstance() :: storageSuffix: '+this.storageSuffix,8);

		object = document.createElement('object');
		object.id = 'DS_userScript_SWFStore'+this.storageSuffix;
		object.width = '300px';
		object.height = '200px';
		object.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
		object.type = 'application/x-shockwave-flash';
		object.data = this.options.SWFAddress;
		object.innerHTML =
			'<param name="movie" value="' + this.options.SWFAddress + '" />'+
			'<param name="allowScriptAccess" value="always" />'+
			'<param name="quality" value="low" />'+
			'<param name="swLiveConnect" value="true" />'+
			'<param name="flashVars" value="storageReady=DS_userScript_SWFStore.contentReady&displaySettings=DS_userScript_SWFStore.displaySettings&settingsClosed=DS_userScript_SWFStore.settingsClosed" />'+
			'';

		div.appendChild(object);
		this.store = object;
	},
	contentReady : function () {
		var res = this.initStorage();
		if (res != 'STOR_CREATED' && res != 'STOR_READY') {
			this.options.logger('SWFStore.init() => FAILED: '+res, 0);
		} else {
			this.options.logger('SWFStore.init() => DONE: '+res, 8);
			this.options.logger('SWFStore.init() => getAllKeys(): '+this.store.getAllKeys(), 8);
			this.options.runAfter();
		}

	},
	initStorage : function() {
		this.options.logger('SWFStore.initStorage() :: (typeof this.store): `'+(typeof this.store)+'`', 10);
		this.options.logger('SWFStore.initStorage() :: loading: `'+this.options.storageName+'`', 10);
		return this.store.initStorage(this.options.storageName);
	},
	getValue : function (key) {
		var res = this.store.getValue(key)
		this.options.logger('SWFStore.getValue('+key+')', 10);
		return res;
	},
	setValue : function(key, val) {
		if (this.doSaves) {
			// let's do some prevention
			if (typeof val != 'string') {
				val = JSON.encode(val);
			}
			return this.store.setValue(key, val);
		} else {
			this.options.logger('SWFStore.setValue() => aborting save',0);
			return false;
		}
	},
	removeValue : function(key) {
		if (this.doSaves) {
			return this.store.removeValue(key);
		} else {
			this.options.logger('SWFStore.removeValue() => aborting save',0);
			return false;
		}
	},
	removeStorage : function() {
		if (this.doSaves) {
			return this.store.removeStorage()
		} else {
			this.options.logger('SWFStore.removeStorage() => aborting save',0);
			return false;
		}
	},
	getSize : function() {
		return this.store.getSize();
	},
	getAllKeys : function() {
		return this.store.getAllKeys();
	},

	displaySettings : function() {
		this.options.logger('SWFStore.displaySettings()',8);
		this.doSaves = false;
		document.getElementById('DS_userScript_SWFStoreContainer'+this.storageSuffix).styles.left = '400px';
	},
	settingsClosed : function(flush_result) {
		if (flush_result == 'true') {
			this.doSaves = true;
			this.options.logger('SWFStore.settingsClosed() => flush SUCCESS', 8);
		} else {
			this.options.logger('SWFStore.settingsClosed() => flush FAILED!', 8);
		}
		document.getElementById('DS_userScript_SWFStoreContainer'+this.storageSuffix).styles.left = '-299px';
	},
	_time : Date.now || function() {
		return +new Date;
	}
};

}
/**
 *		LOADER
 * see comments below for explanation of what is going on here
 */
if ((typeof GM_getResourceURL) != "undefined") {
	if ((typeof unsafeWindow.DS_userScript_SWFStore) == 'undefined') {
		unsafeWindow.DS_userScript_SWFStore = {};
		unsafeWindow.JSON = {};
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.charset = 'utf-8';
		script.innerHTML = '(' + DS_userScript_SWFStore_Wrapper + ')();';
		document.body.appendChild(script);
	}
} else {
	var DS_userScript_SWFStore, JSON;
	DS_userScript_SWFStore_Wrapper();
}

/*		END COPY HERE */

/**
 *		LOADER Explained
 *
 * As GM uses unsafeWindow for referencing to an actual page we need to do some "tricks" to inject our script directly into page and not to worry about unsafeWindow latter
 * This can be acheived by putting the source of the script directly into BODY of the displayed page.
 * So here's an explanation how it is being done:
 *
 * as we can't relay on detection of 'unsafeWindow' (it could have been declared by other script) we'll use a GM specific function to detect GM (also not so much reliable but safer than unsafeWindow)
 *
 * "if ((typeof GM_getResourceURL) != "undefined") {"
 *		here we've successfully detected GM
 *
 * we need to be sure that we will not overwrite the existing object so:
 * "if ((typeof unsafeWindow.DS_userScript_SWFStore) == 'undefined') {"
 *		is rather good solution (:
 *
 * as we can't use declaration in format "var var_name;" we need to create a space for new object in unsafeWindow as we're not yet there (:
 * "unsafeWindow.DS_userScript_SWFStore = {};"
 *
 * the next step is to create <script> object
 * "var script = document.createElement('script');"
 *
 * then we should define at least type of the script
 * "script.type = 'text/javascript';"
 *
 * defining charset is useful for langague specific behavior so:
 * "script.charset = 'utf-8';"
 *
 * and here is the funny part (:
 * "script.innerHTML = '(' + DS_userScript_SWFStore_Wrapper + ')();';"
 *
 * as the 'script' variable holds reference to an actual HTML object <script> we can, in modern browsers (which FF is), use innerHTML property to define text of the script
 * this particular solution places all the text of wrapper function in the <script> object and to be absolutley sure that we will not create some unnecessary garbage it places it in anonymous, self-executing, function
 * if we wouldn't prepare "space" for new object ("unsafeWindow.DS_userScript_SWFStore = {};") nothing would happen (:
 *
 * as "document" object refers to an actual displayed document (the one we're running our script on) we can safely use it for injecting the script:
 * "document.body.appendChild(script);"
 *
 * at this moment the whole <script> object was placed at the end of <body> element
 * as the content of the <script> is self-executing we have just successfully created body for previously declared object (:
 *
 * next we're closing the IF for checking object existasnce
 * and after that we have ELSE for every other browser we're running script on
 *
 * this part is simple:

 * we declare our object in global scope
 * "var DS_userScript_SWFStore;"
 *
 * and after that we're running the function that creates body of the object (or the object itself)
 * "DS_userScript_SWFStore_Wrapper();"
 *
 */